对象可见性

Unity网络支持这样一个想法,即并非服务器上的所有GameObjects应该对游戏中的所有玩家都可见。这有时被称为“兴趣区域”,因为玩家只能看到游戏决定的与他们相关或有趣的GameObjects。一些使用此概念的游戏功能包括战争雾,隐形和基于邻近度的可见性。当游戏世界在服务器上非常大或包含许多网络化的GameObjects时,这一点尤其重要。减少对玩家可见的GameObjects集减少了登录时间和持续带宽 - 因为更新只发送给玩家可见的GameObjects

NetworkProximityChecker

限制玩家对GameObject可见性的最简单方法是使用内置的NetworkProximityChecker组件。这与Unity 3D物理或2D物理系统配合使用,只允许玩家看到离他们很近的GameObjects。要使用此组件,请将其添加到您希望限制可见性的联网GameObject的预制中。该NetworkProximityChecker有一些配置参数。比“可见范围”更远的GameObjects对于玩家将不可见,并且每个玩家的可见GameObjects集合将在每“可见更新间隔”秒被重新计算。

GameObject必须有一个物理碰撞器才能与NetworkProximityChecker配合使用。

远程客户端的可见性

当远程客户端上的玩家加入网络游戏时,只有该玩家可见的GameObjects才会在该客户端上产生。所以即使玩家进入一个拥有多个网络游戏对象的大世界,进入世界的时间也可以保持合理。这适用于场景中的网络化GameObject,但不影响资源的加载 - 已注册预制件和场景GameObjects的资源仍将加载。

当一个玩家在世界中移动时,这组可见的GameObjects将会改变。发生这种情况时,客户会被告知这些更改。ObjectHideGameObject不再可见时,会向客户端发送一条消息。处理此消息的默认行为是销毁GameObject。当一个GameObject变得可见时,客户端会收到一条ObjectSpawn消息 - 就像GameObject是第一次创建一样。所以默认情况下,GameObject会像其他任何产生的GameObject一样被实例化。

在主机上的可见性

由于主机与服务器共享相同的场景,因此无法销毁对本地玩家不可见的GameObjects。相反,有一个虚拟函数NetworkBehaviour被调用:

    public virtual void OnSetLocalVisibility(bool vis)
    {
    }

此功能在GameObjects上的所有联网脚本上调用,这些脚本会更改主机上的可见性状态。这允许每个脚本定制它应该如何响应,例如通过禁用HUD元素或渲染器。默认实现NetworkProximityChecker禁用或启用GameObject上的所有Renderer组件。

自定义可见性

NetworkProximityChecker是使用Unity Networking的公开可视化界面实现的。使用这个接口,开发人员应该能够实现他们想要的任何一种可见性规则。每个NetworkIdentity都会跟踪它可见的玩家组。这些被称为GameObject的“观察者”。

NetworkIdentity有一个功能:

    // call this to rebuild the set of players observing this GameObject
    public void RebuildObservers(bool initialize);

NetworkProximityChecker在一个固定的时间间隔调用这个函数在,因此设定为每个玩家可见GameObjects的,因为他们走动更新。

在上面NetworkBehaviour,有一些确定可见性的虚拟功能:

    // called when a new player enters the game
    public override bool OnCheckObserver(NetworkConnection newObserver);

    // called when RebuildObservers is invoked 
    public override bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initial);

OnCheckObservers当新玩家进入游戏时,该功能在每个联网的游戏对象上的服务器上被调用。如果它返回true,那么该玩家将被添加到GameObject的观察者中。该NetworkProximityCheck确实在执行这个功能的一个简单的距离检查。

OnRebuildObservers函数在RebuildObservers被调用时在服务器上被调用。这个函数期望观察者集合被填充可以看到GameObject的玩家。在NetworkServer随后处理发送ObjectHideObjectSpawn基于旧的和新的可视性集之间的差别的消息。用于查找处于该GameObject可见距离范围内的玩家的NetworkProximityChecker用途Physics.OverlapSphere

要找出一个游戏物体是否是一名玩家,检查它的NetworkIdentity是否具有有效的connectionToClient。例如:

    var hits = Physics.OverlapSphere(transform.position, visRange);
    foreach (var hit in hits)
    {
        // (if a GameObject has a connectionToClient, it is a player)
        var uv = hit.GetComponent<NetworkIdentity>();
        if (uv != null && uv.connectionToClient != null)
        {
            observers.Add(uv.connectionToClient);
        }
    }

🔚